package com.link2room.soundwave.facade.impl;

import com.link2room.common.exception.SysException;
import com.link2room.common.jpa.condition.ConditionDetail;
import com.link2room.common.jpa.condition.L2RCondition;
import com.link2room.common.jpa.criteria.CriteriaUtil;
import com.link2room.common.jpa.result.QueryResult;
import com.link2room.common.service.ICommonService;
import com.link2room.common.util.BatchUtil;
import com.link2room.common.util.DateUtil;
import com.link2room.common.util.L2RAssert;
import com.link2room.common.util.TryExceptionUtil;
import com.link2room.enums.exception.SoundwaveSysExceptionEnum;
import com.link2room.jetfire.constant.ReservationConstant;
import com.link2room.jetfire.dto.param.base.ReservationParamDto;
import com.link2room.jetfire.dto.param.inside.ReservationBaseInsideParamDto;
import com.link2room.jetfire.dto.result.base.GcOrderCouponDto;
import com.link2room.jetfire.dto.result.base.ReservationBaseDto;
import com.link2room.soundwave.constant.SoundwaveMnsConstant;
import com.link2room.soundwave.constant.SoundwaveTaskNameConstant;
import com.link2room.soundwave.dto.param.api.MemeberCardPayApiParamDto;
import com.link2room.soundwave.dto.param.base.PmsReservationBaseParamDto;
import com.link2room.soundwave.dto.param.inside.MemeberCardPayInsideParamDto;
import com.link2room.soundwave.dto.param.inside.PmsReservationPayInsideParamDto;
import com.link2room.soundwave.dto.param.inside.ReservationStaInsideParamDto;
import com.link2room.soundwave.dto.result.base.AccountResultDto;
import com.link2room.soundwave.dto.result.base.MemberCardPayDto;
import com.link2room.soundwave.dto.result.base.PmsAccountDto;
import com.link2room.soundwave.entity.L2RYhHotel;
import com.link2room.soundwave.entity.L2RYhReservation;
import com.link2room.soundwave.entity.L2RYhReservationDetail;
import com.link2room.soundwave.entity.L2RYhRmtype;
import com.link2room.soundwave.exception.SoundwaveException;
import com.link2room.soundwave.feign.jetfire.ReservationsFeignService;
import com.link2room.soundwave.service.IYhPmsBaseService;
import com.link2room.soundwave.service.IYhReservationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import yuheng.pms.result.YhOrderReturnDto;
import yuheng.pms.result.YhReserveDto;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Created by VegetaKo on 2016/9/23.
 */
@Component("yhPmsReservationHandlerFacadeService")
public class YhPmsReservationHandlerFacadeServiceImpl extends AbstractReservationHandlerFacadeServiceImpl {
    @Resource
    private ICommonService commonService;
    @Resource
    private IYhPmsBaseService yhPmsBaseService;
    @Resource
    private IYhReservationService yhReservationService;
    @Autowired
    private ReservationsFeignService reservationsFeignService;

    @Override
    public void savePMSReservation(ReservationParamDto reservationParamDto) throws Exception {
        ReservationBaseDto reservationBaseDto = reservationParamDto.getReservationBase();
        String lhotelGroupCode=reservationBaseDto.getLhotelGroupCode();
        String lhotelCode=reservationBaseDto.getLhotelCode();

        if( reservationParamDto.getOperType().equals(ReservationConstant.OPERTYPE.CREATE )){
            if(reservationParamDto.getReservationPriceDtos()==null||reservationParamDto.getReservationPriceDtos().size()==0){
                throw new SoundwaveException(SoundwaveSysExceptionEnum.NO_PRICELIST);
            }
            String l2rRmtype=reservationBaseDto.getRmtype();
            L2RYhHotel querylih = new L2RYhHotel();
            querylih.setLhotelGroupCode( lhotelGroupCode);
            querylih.setLhotelCode( lhotelCode);
            L2RYhHotel l2RYhHotel = commonService.findOneEQ(L2RYhHotel.class, querylih);
            if(l2RYhHotel==null){
                throw new SoundwaveException(SoundwaveSysExceptionEnum.YHPMS_MAPPINGHOTEL_NOT_EXIT);
            }
            L2RYhRmtype querylir = new L2RYhRmtype();
            querylir.setLhotelGroupCode( lhotelGroupCode);
            querylir.setLhotelCode( lhotelCode);
            querylir.setL2RRmtype(l2rRmtype);
            L2RYhRmtype l2RYhRmtype = commonService.findOneEQ(L2RYhRmtype.class, querylir);
            if(l2RYhRmtype==null){
                throw new SoundwaveException(SoundwaveSysExceptionEnum.YHPMS_MAPPINGRMTYPE_NOT_EXIT);
            }
            String rmtype=l2RYhRmtype.getPmsRmtype();

            L2RYhReservation queryL2R = new L2RYhReservation();
            queryL2R.setLhotelGroupCode(reservationParamDto.getReservationBase().getLhotelGroupCode() );
            queryL2R.setLhotelCode( reservationParamDto.getReservationBase().getLhotelCode());
            queryL2R.setL2RNo( reservationParamDto.getReservationBase().getL2RNo());
            QueryResult<L2RYhReservation> l2RYhReservationQueryResult = commonService.findAllEQ(L2RYhReservation.class, queryL2R);

            if(l2RYhReservationQueryResult.getResultlist()==null||l2RYhReservationQueryResult.getResultlist().size()==0){

                YhOrderReturnDto yhOrderReturn = yhPmsBaseService.orderYhReservation(lhotelGroupCode,
                        l2RYhHotel.getGroupCode(),
                        l2RYhHotel.getHotelCode(),
                        reservationParamDto.getReservationBase().getL2RNo(),
                        rmtype,
                        reservationBaseDto,
                        reservationParamDto.getReservationPriceDtos(), Optional.ofNullable(reservationParamDto.getGcOrderCoupons()).filter(value->value.size()>0).map(value->value.get(0)).orElse(new GcOrderCouponDto()));

                yhReservationService.saveYhReservationAll(reservationBaseDto,l2RYhHotel,yhOrderReturn);

                ReservationBaseInsideParamDto reservationBaseInsideParamDto = new ReservationBaseInsideParamDto();
                reservationBaseInsideParamDto.setLhotelGroupCode( reservationBaseDto.getLhotelGroupCode());
                reservationBaseInsideParamDto.setLhotelCode(reservationBaseDto.getLhotelCode() );
                reservationBaseInsideParamDto.setCrsNo( yhOrderReturn.getParentReserveNo() );
                reservationBaseInsideParamDto.setL2RNo( reservationBaseDto.getL2RNo());
                reservationsFeignService.updateReservationSta(reservationBaseInsideParamDto);
            }
        } else{
            this.cancelPMSReservation(reservationParamDto);
        }
    }

    @Override
    public void cancelPMSReservation(ReservationParamDto reservationParamDto) throws Exception {
        L2RYhReservation queryLIR = new L2RYhReservation();
        queryLIR.setLhotelGroupCode(reservationParamDto.getLhotelGroupCode());
        queryLIR.setL2RNo( reservationParamDto.getReservationBase().getL2RNo());
        L2RYhReservation l2RYhReservation  = commonService.findOneEQ(L2RYhReservation.class, queryLIR);
        Optional.ofNullable(l2RYhReservation).map(TryExceptionUtil.of(value->{
            yhPmsBaseService.cancelYhReservation(reservationParamDto.getLhotelGroupCode(),value.getGroupCode(),value.getHotelCode(),value.getCrsNo());
            yhReservationService.updateYhReservationAll(value,ReservationConstant.YH_RESSTA.C);
            ReservationBaseInsideParamDto reservationBaseInsideParamDto = new ReservationBaseInsideParamDto();
            reservationBaseInsideParamDto.setLhotelGroupCode( value.getLhotelGroupCode());
            reservationBaseInsideParamDto.setLhotelCode(value.getLhotelCode() );
            reservationBaseInsideParamDto.setCrsNo( value.getCrsNo() );
            reservationBaseInsideParamDto.setL2RNo( value.getL2RNo());
            reservationBaseInsideParamDto.setResSta(ReservationConstant.RESSTA.X);
            reservationsFeignService.updateReservationSta(reservationBaseInsideParamDto);
            return value;
        })).orElseThrow(()->new SysException(SoundwaveSysExceptionEnum.PMSRESER_NOT_EXIT));
    }

    @Override
    public void savePMSReservationPay(PmsReservationPayInsideParamDto pmsReservationPayInsideParamDto) throws Exception {
        L2RYhReservation queryLIR = new L2RYhReservation();
        queryLIR.setLhotelGroupCode(pmsReservationPayInsideParamDto.getLhotelGroupCode());
        queryLIR.setL2RNo( pmsReservationPayInsideParamDto.getL2RNo());
        L2RYhReservation l2RYhReservation  = commonService.findOneEQ(L2RYhReservation.class, queryLIR);
        L2RYhHotel querylih = new L2RYhHotel();
        querylih.setLhotelGroupCode( l2RYhReservation.getLhotelGroupCode());
        querylih.setLhotelCode( l2RYhReservation.getLhotelCode());
        L2RYhHotel l2RYhHotel = commonService.findOneEQ(L2RYhHotel.class, querylih);
        if(l2RYhHotel==null){
            throw new SoundwaveException(SoundwaveSysExceptionEnum.YHPMS_MAPPINGHOTEL_NOT_EXIT);
        }
        if(l2RYhReservation!=null) {
            yhPmsBaseService.saveYhReservationPay(pmsReservationPayInsideParamDto.getLhotelGroupCode(),
                    l2RYhHotel.getGroupCode(),
                    l2RYhHotel.getHotelCode(),
                    l2RYhReservation.getCrsNo(),
                    pmsReservationPayInsideParamDto.getPmsResType(),
                    pmsReservationPayInsideParamDto.getTaCode(),
                    pmsReservationPayInsideParamDto.getAmount());
        }else {
            throw new SoundwaveException(SoundwaveSysExceptionEnum.PMSRESER_NOT_EXIT);
        }
    }

    @Override
    public void syncReservationSta(ReservationStaInsideParamDto reservationStaInsideParamDto) throws Exception {
        List<String> pmsStas = new ArrayList<>();
        pmsStas.add(ReservationConstant.YH_RESSTA.R);
        //pmsStas.add(ReservationConstant.YH_RESSTA.C);
        pmsStas.add(ReservationConstant.YH_RESSTA.I);
        L2RCondition stockConfition=new L2RCondition();
        stockConfition.setAndConditions(new ConditionDetail[]{
                new ConditionDetail(L2RYhReservation.BaseEntity_.lhotelGroupCode.toString(), CriteriaUtil.Operator.EQ, reservationStaInsideParamDto.getLhotelGroupCode() ),
                new ConditionDetail(L2RYhReservation.BaseEntity_.lhotelCode.toString(), CriteriaUtil.Operator.EQ, reservationStaInsideParamDto.getLhotelCode() ),
                new ConditionDetail(L2RYhReservation.L2RYhReservation_.pmsSta.toString(), CriteriaUtil.Operator.IN,pmsStas)
        });
        QueryResult<L2RYhReservation> l2RYhReservationQueryResult = commonService.findAllByCondition(L2RYhReservation.class, stockConfition);
        if(  null !=l2RYhReservationQueryResult.getResultlist()&& l2RYhReservationQueryResult.getResultlist().size()>0){
            List<PmsReservationBaseParamDto> pmsReservationBaseParamDtos =new ArrayList<>();

            for (L2RYhReservation l2RYhReservation : l2RYhReservationQueryResult.getResultlist()) {
                PmsReservationBaseParamDto pmsReservationBaseParamDto=new PmsReservationBaseParamDto();
                pmsReservationBaseParamDto.setLhotelGroupCode(l2RYhReservation.getLhotelGroupCode());
                pmsReservationBaseParamDto.setPmsHotelGroupCode(l2RYhReservation.getGroupCode());
                pmsReservationBaseParamDto.setCrsNo(l2RYhReservation.getCrsNo());
                pmsReservationBaseParamDto.setLhotelCode(l2RYhReservation.getLhotelCode());
                pmsReservationBaseParamDto.setPmsHotelCode(l2RYhReservation.getHotelCode());
                pmsReservationBaseParamDtos.add(pmsReservationBaseParamDto);
            }
            BatchUtil.beginBatchTask(SoundwaveMnsConstant.QUEUE_PMSRESSTA,
                    SoundwaveTaskNameConstant.SAVE_PMS_RESSTA,
                    pmsReservationBaseParamDtos);
        }
    }

    @Override
    public void syncPMSHotelReservationSta(PmsReservationBaseParamDto pmsReservationBaseParamDto) throws Exception {
        String crsNo=pmsReservationBaseParamDto.getCrsNo();
        L2RAssert.stringBlank(crsNo,"CRSNO为空");
        L2RYhReservation queryLIR = new L2RYhReservation();
        queryLIR.setCrsNo(crsNo );
        L2RYhReservation l2RYhReservation = commonService.findOneEQ(L2RYhReservation.class, queryLIR);
        Optional.ofNullable(l2RYhReservation).map(TryExceptionUtil.of(event->{
            return this.updatePmsSta(event);
        })).orElseThrow(()->new SoundwaveException(SoundwaveSysExceptionEnum.PMSRESER_NOT_EXIT));

    }

    private L2RYhReservation updatePmsSta(L2RYhReservation l2RYhReservation) throws Exception {
        List<YhReserveDto> yhReserveDtos=yhPmsBaseService.queryYhReservation(l2RYhReservation.getLhotelGroupCode(),
                l2RYhReservation.getGroupCode(),
                l2RYhReservation.getHotelCode(),
                l2RYhReservation.getL2RNo());
        L2RYhReservationDetail queryYhReservationDetail=new L2RYhReservationDetail();
        queryYhReservationDetail.setLhotelGroupCode(l2RYhReservation.getLhotelGroupCode());
        queryYhReservationDetail.setLhotelCode(l2RYhReservation.getLhotelCode());
        queryYhReservationDetail.setCrsNo(l2RYhReservation.getCrsNo());
        QueryResult<L2RYhReservationDetail> l2RYhReservationDetailResult =commonService.findAllEQ(L2RYhReservationDetail.class,queryYhReservationDetail);
        List<L2RYhReservationDetail> l2RYhReservationDetailList= Optional.ofNullable(l2RYhReservationDetailResult.getResultlist()).map(TryExceptionUtil.of(l2RYhReservationDetails -> {
            return l2RYhReservationDetails.stream().map(l2RYhReservationDetail -> yhReserveDtos.stream().filter(
                    yhReserveDto -> Objects.equals(l2RYhReservationDetail.getSerialNo(), yhReserveDto.getSerial())).findFirst().map(
                    TryExceptionUtil.of(yhReserveDto -> {
                        l2RYhReservationDetail.setStatus(yhReserveDto.getStatus());
                        l2RYhReservationDetail.setHstatus(yhReserveDto.getHStatus());
                        l2RYhReservationDetail.setActualRate(new BigDecimal(yhReserveDto.getActualRate()));
                        try {
                            l2RYhReservationDetail.setArrivalDate(DateUtil.parseDateNoTime(yhReserveDto.getArrivalDate(),"yyyy/MM/dd HH:mm:ss"));
                        }catch (Exception e){
                            try {
                                l2RYhReservationDetail.setArrivalDate(DateUtil.parseDateNoTime(yhReserveDto.getArrivalDate(),"yyyy/M/d HH:mm:ss"));
                            }catch (Exception e1){
                                try {
                                    l2RYhReservationDetail.setArrivalDate(DateUtil.parseDateNoTime(yhReserveDto.getArrivalDate(),"yyyy/MM/d HH:mm:ss"));
                                }catch (Exception e2){
                                    try {
                                        l2RYhReservationDetail.setArrivalDate(DateUtil.parseDateNoTime(yhReserveDto.getArrivalDate(),"yyyy/M/dd HH:mm:ss"));
                                    }catch (Exception e3){
                                        l2RYhReservationDetail.setArrivalDate(null);
                                    }
                                }
                            }
                        }
                        try {
                            l2RYhReservationDetail.setDepartureDate(DateUtil.parseDateNoTime(yhReserveDto.getDepartureDate(),"yyyy/MM/dd HH:mm:ss"));
                        }catch (Exception e){
                            try {
                                l2RYhReservationDetail.setDepartureDate(DateUtil.parseDateNoTime(yhReserveDto.getDepartureDate(),"yyyy/M/d HH:mm:ss"));
                            }catch (Exception e1){
                                try {
                                    l2RYhReservationDetail.setDepartureDate(DateUtil.parseDateNoTime(yhReserveDto.getDepartureDate(),"yyyy/MM/d HH:mm:ss"));
                                }catch (Exception e2){
                                    try {
                                        l2RYhReservationDetail.setDepartureDate(DateUtil.parseDateNoTime(yhReserveDto.getDepartureDate(),"yyyy/M/dd HH:mm:ss"));
                                    }catch (Exception e3){
                                        l2RYhReservationDetail.setDepartureDate(null);
                                    }
                                }
                            }
                        }
                        l2RYhReservationDetail.setCancelReserveRemarks(yhReserveDto.getCancelReserveRemarks());
                        l2RYhReservationDetail.setName(yhReserveDto.getName());
                        l2RYhReservationDetail.setPayamount(new BigDecimal(yhReserveDto.getPayamount()));
                        l2RYhReservationDetail.setRoomRate(new BigDecimal(yhReserveDto.getRoomRate()));
                        l2RYhReservationDetail.setRoomType(yhReserveDto.getRoomType());
                        l2RYhReservationDetail.setRoomTypeName(yhReserveDto.getRoomTypeName());
                        l2RYhReservationDetail.setTotalAmount(new BigDecimal(yhReserveDto.getTotalAmount()));
                        return l2RYhReservationDetail;
                    })
            ).orElse(l2RYhReservationDetail)).collect(Collectors.toList());
        })).orElse(new ArrayList<>());
        commonService.mergeList(l2RYhReservationDetailList);
        if(l2RYhReservationDetailList.stream().map(value->value.getStatus()).distinct().count()==1){
            l2RYhReservation.setPmsSta(l2RYhReservationDetailList.stream().findFirst().get().getStatus());
            commonService.merge(l2RYhReservation );
            String resSta=null;
            switch (l2RYhReservation.getPmsSta()){
                case ReservationConstant.YH_RESSTA.R:
                    resSta=ReservationConstant.RESSTA.R;
                    break;
                case ReservationConstant.YH_RESSTA.C:
                    resSta=ReservationConstant.RESSTA.X;
                    break;
                case ReservationConstant.YH_RESSTA.I:
                    resSta=ReservationConstant.RESSTA.I;
                    break;
                case ReservationConstant.YH_RESSTA.S:
                    resSta=ReservationConstant.RESSTA.S;
                    break;
                case ReservationConstant.YH_RESSTA.O:
                    resSta=ReservationConstant.RESSTA.O;
                    break;
                default:
                    break;
            }

            ReservationBaseInsideParamDto reservationBaseInsideParamDto = new ReservationBaseInsideParamDto();
            reservationBaseInsideParamDto.setLhotelGroupCode( l2RYhReservation.getLhotelGroupCode());
            reservationBaseInsideParamDto.setLhotelCode(l2RYhReservation.getLhotelCode() );
            reservationBaseInsideParamDto.setResSta( resSta);
            reservationBaseInsideParamDto.setL2RNo( l2RYhReservation.getL2RNo());
            reservationBaseInsideParamDto.setCrsNo(l2RYhReservation.getCrsNo());
            reservationsFeignService.updateReservationSta(reservationBaseInsideParamDto);
        }
        return l2RYhReservation;
    }

    @Override
    QueryResult<PmsAccountDto> listPmsAccounts(PmsReservationBaseParamDto pmsReservationBaseParamDto) throws Exception {
       return null;
    }

    @Override
    AccountResultDto getAccountResult(PmsReservationBaseParamDto pmsReservationBaseParamDto) throws Exception {
        return null;
    }

    @Override
    String memberCardPrepay(MemeberCardPayInsideParamDto memeberCardPayInsideParamDto) throws Exception {
        return null;
    }

    @Override
    MemberCardPayDto memberCardPay(MemeberCardPayApiParamDto memeberCardPayApiParamDto) throws Exception {
        return null;
    }
}
